#include "GY_GraphicsPolygonItem.h"
#include <QDebug>
#include <QMatrix>

GY_GraphicsPolygonItem::GY_GraphicsPolygonItem(const QString &guid, QGraphicsItem *parent)
    :GY_BasicsGraphicsObject(guid,this,parent),m_pointSize(0)
{
    //图元类型
    GY_Object::setUserData(GY_ENUM::ClassType,QVariant("PolygonItem"));
    initializationPropertyInfo();
    updataPen();
    updataBrush();
    drawPolygon();
    connect(this, &GY_BasicsGraphicsObject::updateDrawSig,this,&GY_GraphicsPolygonItem::drawPolygon);
}

bool GY_GraphicsPolygonItem::drawPolygon()
{
    quint32 i{};
    QPainterPath path = this->path();
    path.clear();
    QMap<QVariant,QPointF> tempEditPointF = this->getEditPointF();
    for(i = 0; i < m_pointSize; i++)
    {
        QString  pointName = QString("point%1").arg(i);
        if(!tempEditPointF.contains(pointName))
            continue;
        //设置current position（开始的坐标）
        if(i == 0)
        {
            path = QPainterPath(tempEditPointF[pointName]);
            continue;
        }
        path.lineTo(tempEditPointF[pointName]);
    }
    if(i < 3)
    {
        return false;
    }
    if(!m_PropertyInfoMap["IsOpen"].propertyValue.toBool())
        path.closeSubpath();
    this->setPath(path);
    return true;
}

void GY_GraphicsPolygonItem::initializationPropertyInfo()
{
    /*updatePoint属性的数据
     * QVariant 点的属性名
     * QPointF 点的数据 */
    QMap<QVariant,QPointF> point;
    point.insert("point0",QPointF(0,0));
    QVariant var;
    var.setValue(point);

    /*
     *LineStyle属性的数据
     * QVector<qreal>中index(0)是Qt::PenCapStyle、Qt::PenJoinStyle与Qt::PenStyle的组合,index(1)为线条粗细，之后是自定义钢笔样式的数据 */
    QVector<qreal> varStyle;
    int style = Qt::SquareCap|Qt::BevelJoin|Qt::CustomDashLine;
    varStyle<<style<<2<<3<<2<<4<<5<<6<<7;

    //FillGradient渐变数据
    int gradientSpread = QGradient::ReflectSpread;//指定如何填充渐变之外的区域
    QColor colorStart = QColor(0,255,0);//开始颜色
    QColor colorStop = QColor(0,0,255);//结束颜色
    int gradientType = QGradient::LinearGradient;//指定渐变的类型
    QPointF pointFStart = QPointF(0,0);//开始的坐标或中心点坐标
    QPointF pointFStop = QPointF(25,25);//结束的坐标或径向梯度的焦点坐标
    qreal centerRadius = 100;//中心半径
    qreal focalRadius = 100;//径向梯度的焦点半径
    QVector<qreal> varGradientStyle;
    varGradientStyle<<gradientSpread<<colorStart.rgb()<<colorStop.rgb()<<gradientType<<pointFStart.x()
                   <<pointFStart.y()<<pointFStop.x()<<pointFStop.y()<<centerRadius<<focalRadius;

    GY_PropertyInfo PtsArrayCapacity;
    PtsArrayCapacity.propertyName = "PtsArrayCapacity";
    PtsArrayCapacity.propertyValue = 3;
    m_capacitySize = 3;
    PtsArrayCapacity.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::setPtsArrayCapacity;
    m_PropertyInfoMap.insert("PtsArrayCapacity",PtsArrayCapacity);

    GY_PropertyInfo PtsArraySize;
    PtsArraySize.propertyName = "PtsArraySize";
    PtsArraySize.propertyValue = 3;
    PtsArraySize.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::setPtsArraySize;
    m_PropertyInfoMap.insert("PtsArraySize",PtsArraySize);

    GY_PropertyInfo updatePoint;
    updatePoint.propertyName = "updatePoint";
    updatePoint.propertyValue =  var;
    updatePoint.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::updatePoint;
    m_PropertyInfoMap.insert("updatePoint",updatePoint);

    GY_PropertyInfo addPoint;
    addPoint.propertyName = "addPoint";
    addPoint.propertyValue = QPointF();
    addPoint.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::addPoint;
    m_PropertyInfoMap.insert("addPoint",addPoint);

    GY_PropertyInfo addPointAfter;
    addPointAfter.propertyName = "addPointAfter";
    addPointAfter.propertyValue = var;
    addPointAfter.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::addPointAfter;
    m_PropertyInfoMap.insert("addPointAfter",addPointAfter);

    GY_PropertyInfo addPointBefore;
    addPointBefore.propertyName = "addPointBefore";
    addPointBefore.propertyValue = var;
    addPointBefore.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::addPointBefore;
    m_PropertyInfoMap.insert("addPointBefore",addPointBefore);

    GY_PropertyInfo deletePoint;
    deletePoint.propertyName = "deletePoint";
    deletePoint.propertyValue = var;
    deletePoint.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::deletePoint;
    m_PropertyInfoMap.insert("deletePoint",deletePoint);

    GY_PropertyInfo PenOpacity;
    PenOpacity.propertyName = "PenOpacity";
    PenOpacity.propertyValue = 1;
    PenOpacity.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::updatePenOpacity;
    m_PropertyInfoMap.insert("PenOpacity",PenOpacity);

    GY_PropertyInfo LineStyle;
    LineStyle.propertyName = "LineStyle";
    LineStyle.propertyValue = QVariant::fromValue(varStyle);
    LineStyle.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::updateLineStyle;
    m_PropertyInfoMap.insert("LineStyle",LineStyle);

    GY_PropertyInfo PenColor;
    PenColor.propertyName = "PenColor";
    PenColor.propertyValue = QColor(0,255,255);
    PenColor.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::updatePenColor;
    m_PropertyInfoMap.insert("PenColor",PenColor);

    GY_PropertyInfo PenAttributes;
    PenAttributes.propertyName = "PenAttributes";
    PenAttributes.propertyValue = false;
    PenAttributes.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::updatePenAttributes;
    m_PropertyInfoMap.insert("PenAttributes",PenAttributes);

    GY_PropertyInfo FillOpacity;
    FillOpacity.propertyName = "FillOpacity";
    FillOpacity.propertyValue = 1;
    FillOpacity.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::updateFillOpacity;
    m_PropertyInfoMap.insert("FillOpacity",FillOpacity);

    //Pattern填充图案数据
    QVector<QPoint> points;
    points << QPoint(0,1)<< QPoint(2,1)<< QPoint(3,1) << QPoint(5,1)<< QPoint(5,15) << QPoint(14,8);
    GY_PropertyInfo Pattern;
    Pattern.propertyName = "Pattern";
    Pattern.propertyValue = QVariant();
    Pattern.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::updatePattern;
    m_PropertyInfoMap.insert("Pattern",Pattern);

    GY_PropertyInfo FillGradient;
    FillGradient.propertyName = "FillGradient";
    FillGradient.propertyValue = QVariant::fromValue(varGradientStyle);
    FillGradient.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::updateFillGradient;
    m_PropertyInfoMap.insert("FillGradient",FillGradient);

    GY_PropertyInfo FillColor;
    FillColor.propertyName = "FillColor";
    FillColor.propertyValue = QColor();
    FillColor.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::updateFillColor;
    m_PropertyInfoMap.insert("FillColor",FillColor);

    GY_PropertyInfo FillStyle;
    FillStyle.propertyName = "FillStyle";
    FillStyle.propertyValue = true;
    FillStyle.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::updateFillStyle;
    m_PropertyInfoMap.insert("FillStyle",FillStyle);

    GY_PropertyInfo FillAttributes;
    FillAttributes.propertyName = "FillAttributes";
    FillAttributes.propertyValue = false;
    FillAttributes.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::updateFillAttributes;
    m_PropertyInfoMap.insert("FillAttributes",FillAttributes);

    GY_PropertyInfo HaloLineWidth;
    HaloLineWidth.propertyName = "HaloLineWidth";
    HaloLineWidth.propertyValue = qreal();
    HaloLineWidth.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::setHaloLineWidth;
    m_PropertyInfoMap.insert("HaloLineWidth",HaloLineWidth);

    GY_PropertyInfo HaloColor;
    HaloColor.propertyName = "HaloColor";
    HaloColor.propertyValue = false;
    HaloColor.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::setHaloColor;
    m_PropertyInfoMap.insert("HaloColor",HaloColor);

    GY_PropertyInfo IsAntialiased;
    IsAntialiased.propertyName = "IsAntialiased";
    IsAntialiased.propertyValue = false;
    IsAntialiased.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::updateIsAntialiased;
    m_PropertyInfoMap.insert("IsAntialiased",IsAntialiased);

    GY_PropertyInfo IsFilled;
    IsFilled.propertyName = "IsFilled";
    IsFilled.propertyValue = true;
    IsFilled.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::updateIsFilled;
    m_PropertyInfoMap.insert("IsFilled",IsFilled);

    GY_PropertyInfo IsOutLined;
    IsOutLined.propertyName = "IsOutLined";
    IsOutLined.propertyValue = true;
    IsOutLined.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::updateIsOutLined;
    m_PropertyInfoMap.insert("IsOutLined",IsOutLined);

    GY_PropertyInfo IsHaloed;
    IsHaloed.propertyName = "IsHaloed";
    IsHaloed.propertyValue = false;
    IsHaloed.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::setIsHaloed;
    m_PropertyInfoMap.insert("IsHaloed",IsHaloed);

    GY_PropertyInfo IsOpen;
    IsOpen.propertyName = "IsOpen";
    IsOpen.propertyValue = false;
    IsOpen.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::updateIsOpen;
    m_PropertyInfoMap.insert("IsOpen",IsOpen);

    GY_PropertyInfo ObjectName;
    ObjectName.propertyName = "ObjectName";
    ObjectName.propertyValue = QString();
    ObjectName.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::updateObjectName;
    m_PropertyInfoMap.insert("ObjectName",ObjectName);
}

void GY_GraphicsPolygonItem::drawHalo()
{

}

bool GY_GraphicsPolygonItem::addPointInBulk(quint32 count)
{
    for(quint32 i{}; i < count; i++)
    {
        QString pointName = QString("point%1").arg(m_pointSize);
        QPointF temp(0,0);
        if(m_pointDeleteInfoMap.contains(m_pointSize))
            temp = m_pointDeleteInfoMap[m_pointSize].pointValue;
        if(m_pointDeleteInfoMap.size() <= 64)
            m_pointDeleteInfoMap.insert(m_pointSize, PointInfo(pointName, temp));
        this->setEditPointF(pointName, temp);
        m_pointSize++;
    }
    return true;
}

bool GY_GraphicsPolygonItem::deletePointInBulk(quint32 count)
{
    QMap<QVariant,QPointF> tempEditPointF = this->getEditPointF();
    for(quint32 i{}; i < count; i++)
    {
        QString pointName = QString("point%1").arg(--m_pointSize);
        if(m_pointDeleteInfoMap.contains(m_pointSize))
            m_pointDeleteInfoMap.insert(m_pointSize, PointInfo(pointName, tempEditPointF[pointName]));
        this->deleeteEditPointF(pointName);
    }
    return true;
}

//void GY_GraphicsPolygonItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
//{
//    painter->setRenderHint(QPainter::Antialiasing,
//                           m_PropertyInfoMap["IsAntialiased"].propertyValue.value<bool>());
//    painter->drawPath(this->path());
//    QGraphicsPathItem::paint(painter, option, widget);
//}

bool GY_GraphicsPolygonItem::setPtsArrayCapacity(const QString &name, const QVariant &value)
{
    if(name != "PtsArrayCapacity")
        return false;
    if(!value.canConvert<qint32>())
        return false;
    quint32 valueSize = value.toUInt();
    m_PropertyInfoMap["PtsArrayCapacity"].propertyValue = valueSize;
    m_capacitySize = valueSize;
    if( valueSize < m_pointSize)
    {
        m_PropertyInfoMap["PtsArraySize"].propertyValue = valueSize;
        deletePointInBulk(m_pointSize - valueSize);
    }
    return true;
}

bool GY_GraphicsPolygonItem::setPtsArraySize(const QString &name, const QVariant &value)
{
    if(name != "PtsArraySize")
        return false;
    if(!value.canConvert<quint32>())
        return false;
    quint32 valueSize = value.toUInt();
    m_PropertyInfoMap["PtsArraySize"].propertyValue = valueSize;
    if(valueSize < m_pointSize)
        deletePointInBulk(m_pointSize - valueSize);
    else
    {
        if(valueSize > m_capacitySize)
            setPtsArrayCapacity("PtsArrayCapacity",valueSize);
        addPointInBulk(valueSize - m_pointSize);
    }
    return true;
}

bool GY_GraphicsPolygonItem::updatePoint(const QString &name, const QVariant &value)
{
    if(name != "updatePoint")
        return false;
    if(!value.canConvert<QMap<QVariant,QPointF>>())
        return false;
    QMap<QVariant,QPointF> mapPoint = value.value<QMap<QVariant,QPointF>>();
    for(quint32 i{}; i < m_pointSize; i++)
    {
        QString pointName = QString("point%1").arg(i);
        if(!mapPoint.contains(pointName))
            continue;
        mapPoint[pointName] = this->mapFromScene(mapPoint[pointName]);
        m_PropertyInfoMap["updatePoint"].propertyValue = mapPoint[pointName];
        this->setEditPointF(pointName,mapPoint[pointName]);
    }
    drawPolygon();
    return true;
}

bool GY_GraphicsPolygonItem::addPoint(const QString &name, const QVariant &value)
{
    if(name != "addPoint")
        return false;
    if(!value.canConvert<QPointF>())
        return false;
    QPointF point = value.value<QPointF>();

    //应用鼠标左键单击添加的场景
    QString pointName = QString("point%1").arg(m_pointSize);
    this->setEditPointF(pointName, point);
    if(m_pointDeleteInfoMap.size() <= 64)
        m_pointDeleteInfoMap.insert(m_pointSize,PointInfo(pointName,point));
    m_pointSize ++;
    m_PropertyInfoMap["addPoint"].propertyValue = point;
    setPtsArraySize("PtsArraySize",m_pointSize);
    drawPolygon();
    return true;
}

bool GY_GraphicsPolygonItem::addPointAfter(const QString &name, const QVariant &value)
{
    if(name != "addPointAfter")
        return  false;
    if(!value.canConvert<QString>())
        return false;
    QString pointName = value.value<QString>();
    QMap<QVariant,QPointF> mapEditPointF = this->getEditPointF();
    //应用鼠标右键某个点，并点击在这个点之后添加的场景
    for(quint32 i{}; i < m_pointSize; i++)
    {
        QString findName = QString("point%1").arg(i);
        if(pointName != findName)
            continue;
        bool isEqual = (i == m_pointSize-1);
        QPointF temp = (mapEditPointF[findName] + mapEditPointF[QString("point%1").arg(i + 1 - ( isEqual *( i + 1)))])/ 2;
        m_PropertyInfoMap["addPointAfter"].propertyValue = temp;
        for(quint32 y{i+1}; y < m_pointSize; y++)
        {
            findName = QString("point%1").arg(y);
            this->setEditPointF(findName, temp);
            temp = mapEditPointF[findName];
        }
        this->setEditPointF(QString("point%1").arg(m_pointSize), temp);
        if(m_pointDeleteInfoMap.size() <= 64)
            m_pointDeleteInfoMap.insert(m_pointSize,PointInfo(QString("point%1").arg(m_pointSize),temp));
        m_pointSize ++;
        setPtsArraySize("PtsArraySize",m_pointSize);
    }
    return  true;
}

bool GY_GraphicsPolygonItem::addPointBefore(const QString &name, const QVariant &value)
{
    if(name != "addPointBefore")
        return  false;
    if(!value.canConvert<QString>())
        return false;
    QString pointName = value.value<QString>();
    QMap<QVariant,QPointF> mapEditPointF = this->getEditPointF();
    //应用鼠标右键某个点，并点击在这个点之前添加的场景
    for(quint32 i{}; i < m_pointSize; i++)
    {
        QString findName = QString("point%1").arg(i);
        if(pointName != findName)
            continue;
        bool isEqual = (i == 0);
        QPointF temp = (mapEditPointF[findName] + mapEditPointF[QString("point%1").arg((isEqual * m_pointSize + i - 1))]) / 2;
        m_PropertyInfoMap["addPointBefore"].propertyValue = temp;
        for(quint32 y{i}; y < m_pointSize; y++)
        {
            findName = QString("point%1").arg(y);
            this->setEditPointF(findName, temp);
            temp =  mapEditPointF[findName];
        }
        this->setEditPointF( QString("point%1").arg(m_pointSize),temp);
        if(m_pointDeleteInfoMap.size() <= 64)
            m_pointDeleteInfoMap.insert(m_pointSize,PointInfo(QString("point%1").arg(m_pointSize),temp));
        m_pointSize ++;
        setPtsArraySize("PtsArraySize",m_pointSize);
    }
    return true;
}

bool GY_GraphicsPolygonItem::deletePoint(const QString &name, const QVariant &value)
{
    if(name != "deletePoint")
        return false;
    if(!value.canConvert<QString>())
        return false;
    QString pointName = value.value<QString>();
    QMap<QVariant,QPointF> mapEditPointF = this->getEditPointF();
    for(quint32 i{}; i < m_pointSize; i++)
    {
        QString findName = QString("point%1").arg(i);
        if(pointName != findName)
            continue;
        if(m_pointDeleteInfoMap.contains(i))
            m_pointDeleteInfoMap.insert(i,PointInfo(findName,mapEditPointF[findName]));
        m_PropertyInfoMap["deletePoint"].propertyValue = mapEditPointF[findName];
        for(quint32 y{i}; y < m_pointSize; y++)
        {
            findName = QString("point%1").arg(y);
            QPointF temp =  mapEditPointF[QString("point%1").arg(y+1)];
            this->setEditPointF(findName, temp);
        }
    }
    m_pointSize--;
    this->deleeteEditPointF(QString("point%1").arg(m_pointSize));
    setPtsArraySize("PtsArraySize",m_pointSize);

    return true;
}

//TODO::设置光晕宽度（限制0-10）
bool GY_GraphicsPolygonItem::setHaloLineWidth(const QString &name, const QVariant &value)
{
    if(name != "HaloLineWidth")
        return false;
    if(!value.canConvert<qreal>())
        return false;
    qreal qvalue = value.value<qreal>();
    m_PropertyInfoMap["HaloLineWidth"].propertyValue = qvalue;
    if(qvalue < 0)
        m_PropertyInfoMap["HaloLineWidth"].propertyValue = 0;
    if(qvalue > 10)
        m_PropertyInfoMap["HaloLineWidth"].propertyValue = 10;
    return true;
}

//TODO::设置光晕颜色
bool GY_GraphicsPolygonItem::setHaloColor(const QString &name, const QVariant &value)
{
    if(name != "HaloColor")
        return false;
    QColor color = value.value<QColor>();
    m_PropertyInfoMap["HaloColor"].propertyValue = color;
    return true;
}

//设置是否有光晕
bool GY_GraphicsPolygonItem::setIsHaloed(const QString &name, const QVariant &value)
{
    if(name != "IsHaloed")
        return false;
    if(!value.canConvert<bool>())
        return false;
    bool isHaloed = value.value<bool>();
    m_PropertyInfoMap["IsHaloed"].propertyValue = isHaloed;
    if(isHaloed){
        for(quint32 i{}; i < m_pointSize; i++)
        {
            QString  qtype = QString("point%1").arg(i);
            if(!m_PropertyInfoMap.contains(qtype))
                continue;
            GY_PropertyInfo PtsArrayCapacity;
            PtsArrayCapacity.propertyName = QString("haloLine_%1").arg(i);
            PtsArrayCapacity.propertyValue =m_PropertyInfoMap[qtype].propertyValue.value<QPointF>();
            PtsArrayCapacity.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsPolygonItem::updatePoint;
            m_PropertyInfoMap.insert(PtsArrayCapacity.propertyName,PtsArrayCapacity);
        }
    }
    return true;
}


